package query

import (
	"gorm.io/gorm"
	"math"
	"sync"
)

// Pager 分页器
type Pager[T any] struct {
	DB *gorm.DB `json:"DB,omitempty"`
	// 分页大小
	PageSize int `json:"pageSize,omitempty"`
	// 当前页数
	PageNum int `json:"pageNum,omitempty"`
}

type PageBase struct {
	// 当前页码
	Page int `json:"page,omitempty"`
	// 总记录数
	Total int64 `json:"total,omitempty"`
	// 总页码数
	TotalPages int `json:"totalPages,omitempty"`
}

type SearchResult[T any] struct {
	PageBase
	// 当前页的记录数
	Hits []T `json:"hits,omitempty"`
	// 当前页的id数
	Ids []interface{} `json:"ids,omitempty"`
}

func (p *Pager[T]) Page() *SearchResult[T] {
	var (
		done  = sync.WaitGroup{}
		total int64
	)
	done.Add(2)
	if p.PageNum < 1 {
		p.PageNum = 1
	}
	if p.PageNum > 50 {
		p.PageNum = 50
	}
	if p.PageSize < 0 || p.PageSize > 100 {
		p.PageSize = 20
	}
	p.DB = p.DB.Session(&gorm.Session{})
	result := new(SearchResult[T])
	// 计算总数
	go p.count(&done, &total)
	// 查询数据
	go p.records(&done, result)
	done.Wait()
	result.Page = p.PageNum
	result.Total = total
	result.TotalPages = int(math.Ceil(float64(total) / float64(p.PageSize)))
	return result
}

func (p *Pager[T]) count(done *sync.WaitGroup, count *int64) {
	p.DB.Count(count)
	done.Done()
}

func (p *Pager[T]) records(done *sync.WaitGroup, result *SearchResult[T]) {
	offset := (p.PageNum - 1) * p.PageSize
	limit := p.PageSize
	result.Hits = make([]T, 0)
	p.DB.Limit(limit).Offset(offset).Find(&result.Hits)
	done.Done()
}
